//!
/**************************************************************************************************************************
 * @file RBBVolume.cpp
 **************************************************************************************************************************/

/**************************************************************************************************************************
 * Includes
 **************************************************************************************************************************/
#include "RBMainPCH.h"

#include "RBBVolume.h"
#include "RBEntity.h"
#include "RBTransform.h"

#include "RBMath.h"
#include "RBMathVector.h"
#include "RBPlane.h"
#include "RBStream.h"

/**************************************************************************************************************************
 * Class implementation
 **************************************************************************************************************************/
RB_IMPLEMENT_COMPONENT(RBBVolume);


/**************************************************************************************************************************
 * Computes Bound's center and radius from data
 **************************************************************************************************************************/
void RBBVolume::ComputeFromData(const float* pPoints, uint32 uiPoints)
{
    float3 minPos(FLT_MAX,FLT_MAX,FLT_MAX);
    float3 maxPos(-FLT_MAX,-FLT_MAX,-FLT_MAX);
    for (uint16 uiPos=0; uiPos<uiPoints; ++uiPos)
    {
        const float3 curPos(pPoints[0],pPoints[1],pPoints[2]);
        pPoints+=3;
		minPos.x = RBMath::Min(curPos.x, minPos.x);
        minPos.y = RBMath::Min(curPos.y, minPos.y);
        minPos.z = RBMath::Min(curPos.z, minPos.z);
        maxPos.x = RBMath::Max(curPos.x, maxPos.x);
        maxPos.y = RBMath::Max(curPos.y, maxPos.y);
        maxPos.z = RBMath::Max(curPos.z, maxPos.z);
    }

    //Center of AABB
    ModelCenter = 0.5f*(minPos + maxPos);
    ModelExtents = maxPos - ModelCenter;
}

/**
 **************************************************************************************************************************
 * Merge rbBVolume into this
 **************************************************************************************************************************/
void RBBVolume::Update(const RBTransform& worldXForm)
{
    Axes[0](0) = worldXForm.Rotate(0,0);
    Axes[0](1) = worldXForm.Rotate(1,0);
    Axes[0](2) = worldXForm.Rotate(2,0);
    Extents[0] = worldXForm.Scale(0) * ModelExtents(0);

    Axes[1](0) = worldXForm.Rotate(0,1);
    Axes[1](1) = worldXForm.Rotate(1,1);
    Axes[1](2) = worldXForm.Rotate(2,1);
    Extents[1] = worldXForm.Scale(1) * ModelExtents(1);

    Axes[2](0) = worldXForm.Rotate(0,2);
    Axes[2](1) = worldXForm.Rotate(1,2);
    Axes[2](2) = worldXForm.Rotate(2,2);
    Extents[2] = worldXForm.Scale(2) * ModelExtents(2);

    float4x4 mat = RBMath::Build(worldXForm);
    float4 pos(ModelCenter.x,ModelCenter.y,ModelCenter.z,1);

    float4 out = mat * pos;
    Center.x = out.x; Center.y = out.y; Center.z = out.z;

}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBBVolume::UpdateEntity( RBEntityHandle handle )
{
    RBEntity& entity = RBEntity::Get(handle);
    uint16 xFormCount = entity.GetComponentCount<RBBVolume>();
    for (uint16  ui=0; ui < xFormCount; ++ui)
    {
        RBHandle<RBBVolume> h = entity.GetComponent<RBBVolume>(ui);
        h->Update(h->WorldXForm());
    }

}

void RBBVolume::copy_members( RBBVolumeHandle dest )
{
    dest->ModelCenter = ModelCenter;
    dest->ModelExtents = ModelExtents;

    for (int i=0; i<3; ++i)
    {
        dest->Axes[i] = Axes[i];
        dest->Extents[i] = Extents[i];
    }
    dest->Center = Center;
}


/**************************************************************************************************************************/
